package msi.agentClasses;

import java.util.Arrays;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

public class Location {
	//sloppy test method
	public static void main(String[] args){
		Location test = new Location();
		System.out.println("New one: "+test.toString());
		test.walk();
		System.out.println("Walked: "+test.toString());
		test.turn(Side.LEFT);
		System.out.println("Turned left: "+test.toString());
		test.turn(Side.LEFT);
		test.turn(Side.LEFT);
		test.turn(Side.LEFT);
		System.out.println("Turned 3x left: "+test.toString());
		test.turn(Side.RIGHT);
		test.turn(Side.RIGHT);
		test.turn(Side.RIGHT);
		System.out.println("Turned 3x right: "+test.toString());
		test.bounceBack();
		System.out.println("Bounced back: "+test.toString());
	}
	
	
	enum Dir {
		WEST,NORTH,EAST,SOUTH
	}
	
	public final static Dir[] directions = {
		Dir.WEST, Dir.NORTH, Dir.EAST, Dir.SOUTH
	};
	
	enum Side {AHEAD, RIGHT, LEFT, BACK}
	
	private Dir facingDir = Dir.EAST;
	private int row = 1;
	private int col = 1;
	
	public Location(){
		
	}
	
	public int getRow(){
		return this.row;
	}
	
	public int getCol(){
		return this.col;
	}
	
	public Dir getDir(){
		return this.getDir();
	}
	
	public String toString(){
		return "Location: {pos: "+row+", "+col+", dir: "+facingDir.toString()+"}";
	}
	
	public void turn(Side side){
		this.facingDir = turn(facingDir,side);
	}
	
	private Dir turn(Dir dir, Side side){
		int now = Arrays.binarySearch(directions, dir);
		now+=(side==Side.LEFT?-1+directions.length:1+directions.length);
		return directions[now%directions.length];
	}
		
		
	public void walk() {
		walk(this.facingDir);
	}
	
	public void bounceBack(){
		Dir dirBack = directions[(Arrays.binarySearch(directions, facingDir)+directions.length/2)%directions.length];
		walk(dirBack);
	}
	
	private void walk(Dir dir){
		switch (dir) {
		case WEST:
			--col;
			break;
		case EAST:
			++col;
			break;
		case SOUTH:
			--row;
			break;
		case NORTH:
			++row;
			break;
		default:
			break;
		}
	}
	
	//for GetPositionString
	public String gps(){
		return this.getTile().toString();
	}
	public WumpusTile getTile(){
		return new WumpusTile(row, col);
	}
	public int getDirInRow(){
		if(this.facingDir.equals(Dir.WEST)){
			return -1;
		}else if(this.facingDir.equals(Dir.EAST)){
			return 1;
		}else{
			return 0;
		}
	}
	public int getDirInCol(){
		if(this.facingDir.equals(Dir.SOUTH)){
			return -1;
		}else if(this.facingDir.equals(Dir.NORTH)){
			return 1;
		}else{
			return 0;
		}
	}
	
	
	public Dir local2World(Side side){
		int offset = 0;
		switch(side){
			case RIGHT:
				offset=1;
				break;
			case BACK:
				offset=2;
				break;
			case LEFT:
				offset=3;
				break;
			default:
				offset=0;
				break;
		}
		int dirIndex = Arrays.binarySearch(directions, this.facingDir);
		return directions[(dirIndex+offset+directions.length)%directions.length];
	}
	
	public WumpusTile getneighbor(Side side){
		return this.getNeighbor(local2World(side));
	}
	
	public WumpusTile getNeighbor(Dir dir){
		switch (dir){
			case NORTH:
				return new WumpusTile(this.row+1,this.col);
			case SOUTH:
				return new WumpusTile(this.row-1,this.col);
			case WEST:
				return new WumpusTile(this.row, this.col-1);
			case EAST:
				return new WumpusTile(this.row, this.col+1);
			default: 
				return null;
		}
	}
	
	public SortedMap<Side,WumpusTile> getSurroundings(){
		SortedMap<Side,WumpusTile> surroundings = new TreeMap<Side,WumpusTile>();
		surroundings.put(Side.AHEAD,this.getneighbor(Side.AHEAD));
		surroundings.put(Side.RIGHT,this.getneighbor(Side.RIGHT));
		surroundings.put(Side.LEFT,this.getneighbor(Side.LEFT));
		surroundings.put(Side.BACK,this.getneighbor(Side.BACK));
		return surroundings;
	}
}
